// Package internal
// Created by GoLand
// @User: lenora
// @Date: 2023/11/27
// @Time: 14:55

package main

import (
	"camp/microbook/internal/middlewares"
	"errors"
	"github.com/fsnotify/fsnotify"
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"log"
	"net/http"
)

func main() {
	//db := initDb()
	//redisClient := initRedis()
	initViper(true)
	initLogger()
	initPrometheus()

	//otelCancel := ioc.InitOtel()
	//defer func() {
	//	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	//	defer cancel()
	//	otelCancel(ctx)
	//}()
	//server := initWebServer(redisClient)
	//app := InitWebServer()
	var app App
	server := app.web
	//
	//initHandler(db, redisClient, server)
	//server := gin.Default()

	for _, consumer := range app.consumer {
		if err := consumer.Start(); err != nil {
			panic(err)
		}
	}
	app.cron.Start()
	defer func() {
		<-app.cron.Stop().Done()
	}()

	server.GET("/hello", func(context *gin.Context) {
		context.String(http.StatusOK, "hello world")
	})
	_ = server.Run(":8081")
}

func useSession(engin *gin.Engine) {
	loginMiddleware := &middlewares.MiddlewareBuilder{}
	// sess_id是一定要放到cookie里面调用时才可以使用的
	// 使用cookie存储数据
	store := cookie.NewStore([]byte("key"))

	// 使用memstore(内存)存储数据
	// 建议newStore中使用两个参数,一个是authentication key 最好是32/64位
	// 第二个参数是encryption key
	//store := memstore.NewStore([]byte("RHVFppP}aV,ZBB?^evYb}_%u=L+c)KuA"), []byte("fnkjnRjpgMZFpynsrSewsOQmtywHtidH"))

	// 使用redis存储数据
	//store, err := redis.NewStore(16, "tcp", "localhost:6377", "", []byte("RHVFppP}aV,ZBB?^evYb}_%u=L+c)KuA"), []byte("fnkjnRjpgMZFpynsrSewsOQmtywHtidH"))
	//if err != nil {
	//	panic(err)
	//}
	// 初始化session
	engin.Use(sessions.Sessions("ssid", store), loginMiddleware.CheckLogin())
}

func useJWT(engin *gin.Engine) {
	loginMiddleware := &middlewares.JwtMiddlewareBuilder{}
	engin.Use(loginMiddleware.CheckLogin())

}

func initViper(watched bool) {
	//读取的配置文件类型
	viper.SetConfigType("yaml")
	//读取的配置文件名称
	viper.SetConfigName("dev")
	//当前工作目录下的config目录
	viper.AddConfigPath("config")
	//最终配置文件为:./config/dev.yaml
	if watched {
		viper.WatchConfig()
		viper.OnConfigChange(func(in fsnotify.Event) {
			log.Println("config is changed")
		})
	}
	//读取配置
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
	v := viper.Get("api.auth")
	log.Println(v)
}

func initViperV1() {
	//@param name 要读取的flag参数
	//@param value 默认值
	//@param usage 使用说明
	configFile := pflag.String("config", "config/config.yaml", "配置文件路径")
	pflag.Parse()
	//viper.SetConfigFile("./config/dev.yaml")
	viper.SetConfigFile(*configFile)
	err := viper.ReadInConfig()
	if err != nil {
		panic(err)
	}
	v := viper.Get("api.auth")
	log.Println(v)
}

// 目前looger使用的是全局是同一等级
// 如有特殊需求可使用依赖注入的形式不同服务使用不同的logger等级
func initLogger() {
	//创建一个开发环境下的logger
	logger, err := zap.NewDevelopment()
	//生产环境下的logger
	//logger, err := zap.NewProduction()
	if err != nil {
		panic(err)
	}
	//默认情况下log的方法调用是不会输出任何内容的,
	//ReplaceGlobals方发用于替换包变量  使得新创建的logger生效
	zap.ReplaceGlobals(logger)
}

func loggerLevel() {
	//记录错误信息,某些不方便暴露的错误信息等
	zap.L().Error("something wrong", zap.Error(errors.New("specific error")))
	//少数出现可接受  频繁出现须注意是否有潜在风险
	zap.L().Warn("something need to warn")
	//记录信息,不一定是错误信息
	zap.L().Info("something happened")
	//记录与第三方/外部组件的交互信息,可至短信发送接口
}

func initPrometheus() {
	go func() {
		//专门提供给prometheus的端口
		http.Handle("/metrics", promhttp.Handler())
		_ = http.ListenAndServe(":8084", nil)
	}()
}
